require "lfs"
require "unity"
require "MPIPond"
local MPIModel = require "MPIModel"
-----------------------------------------------------------------------------
--初始化参数
-- RCS={
	-- num_threads = 10;
	-- dext = 8;                                    -- 物体到空气盒子
	-- farbox_info = { freq={1,2,3,4}; dfarbox = 6; };
	-- source_info = { freq_min = 5; freq_max = 10;  dsrc  = 3; type = "HH", theta = 45; };
	-- boundary = { xm=UPML; };
	-- units = { freq = GHz; dim = mm };
	-- mesh_freq = 12;
	-- name = "unname";
	-- save2file = false;
	-- camera = "3377.21 -3356.18 2213.26 0.4964 0.205616 0.322752 0.779192";
-- };
-----------------------------------------------------------------------------

local RCS2D = MPIModel:new( { 
	dext = 8;                                    -- 物体到空气盒子
	farbox_info = { freq={1,2,3,4}; dfarbox = 6; };
	source_info = { freq_min = 5; freq_max = 10;  dsrc  = 3; type = "HH", theta = 45; };
	boundary = { zm=Periodic; zp=Periodic; };
	units = { freq = GHz; dim = mm };
	mesh_freq = 12;
	name = "unname";
	save2file = false;
	camera = "3377.21 -3356.18 2213.26 0.4964 0.205616 0.322752 0.779192";
})

-----------------------------------------------------------------------------
--创建表和创建元表
-- function RCS:new (o)
	-- o = o or {};
	-- self.__index = self;
	-- setmetatable(o,self)
	-- return o;
-- end
-----------------------------------------------------------------------------

-----------------------------------------------------------------------------
--打印函数
function RCS2D:print( )
	print( "swarm_size:"..self.swarm_size);
	print( "iterations:"..self.iterations);
	print( "inertia:"..self.inertia);
	print( "correction_factor:"..self.correction_factor);
	print( "max_val:"..self.max_val);
	print( "num_iter:"..self.num_iter);
	print( "swarm arr:"..#self.swarm)
	print( "init_type:"..#self.init_type)
	print( "parameter size:"..#self.par)
	print( "parameters:")
	print_table_table(self.par)
end
-----------------------------------------------------------------------------

function RCS2D:init()
	-- local geo = self.geo_ or _geo
	collectgarbage()
	print("collectgarbage");
	collectgarbage()
	
	print( "Geometry clear all objects")
	Geometry.clear_all();
	
	print( "init RCS2D model ..." )
	self:set_threads();
	self:set_boundary();
	self:set_units();
	self:set_mesh_freq();
	self:create_geometry();
	self:create_source();
	self:create_farbox();
	self:create_grabber();
end


function RCS2D:create_scaters()
	local brick = Geometry.Brick:new();
	brick:pt1(0,0,0);
	brick:pt2(10,10,10);
	
	bbox = brick:bbox()

	return {brick}, bbox
end

function RCS2D:create_geometry()
	print( "create geometry...")
	local dfarbox = self.dfarbox_ --or 0.1
	local dext = self.dext-- or 0.1
	self.bbox = {}
	local posxm,posym,poszm,posxp,posyp,poszp;
	-- assert(self.material_,"material is not set in geometry function(self.material_");
	-- assert(self.path_,"invalid model path in geometry function(self.path_)");
	
	objlist,self.bbox = self:create_scaters();	
	self.bbox:extend(dext,dext,0)
	-- self.bbox.bbox_x1 = self.bbox.bbox_x1 - dext ;
	-- self.bbox.bbox_y1 = self.bbox.bbox_y1 - dext;
	-- self.bbox.bbox_z1 = self.bbox.bbox_z1 - dext;
	-- self.bbox.bbox_x2 = self.bbox.bbox_x2 + dext;
	-- self.bbox.bbox_y2 = self.bbox.bbox_y2 + dext;
	-- self.bbox.bbox_z2 = self.bbox.bbox_z2 + dext;
	
	 ---------------------------
	--Boundary Box
	print( "    create boundary box")
	local brick = Geometry.Brick:new()
	brick :name("air box")
	brick :pt1(self.bbox:xmin(),self.bbox:ymin(),self.bbox:zmin())
	brick :pt2(self.bbox:xmax(),self.bbox:ymax(),self.bbox:zmax())
	brick :outline_width(2)
	brick :is_fill(false)
	Geometry.AddShape(brick)
	----------------------------

         for k,v in pairs ( objlist ) do
		print( "    create object: ",v:name())
		Geometry.AddShape(v)
	end
end


function RCS2D:create_source(  )
	print( "create srouce")	
	-------------------------------------
	local type = self.source_info.type;
	local freqmin = self.source_info.freq_min; --����Դ��ʼƵ��
	local freqmax = self.source_info.freq_max; --����Դ��ֹƵ��
	local dsrc = self.source_info.dsrc or 0;
	local theta = self.source_info.theta;
	assert(freqmin,"freqmin is not set in source function(.source_info.freqmin_)");
	assert(freqmax,"freqmax is not set in source function(.source_info.freqmax_)");
	assert(type,"src type is not set in source function(self.type_)");
	-------------------------------------

	-------------------------------------
	--Pulse
	local signal_gauss = Geometry.NewGaussPulse("Gauss Pulse")
	signal_gauss :freq_low(freqmin)
	signal_gauss :freq_high(freqmax)
	self.psig = signal_gauss
	-------------------------------------


	-------------------------------------
	--Source
	local src= Geometry.PlaneWaveSrc:new();
	if type == "HH" then                    
	    src :name("HH PW src")
	    src :polarization_angle(pi/2)
	else
	   src :name("VV PW src")
	end
	src :pt1(self.bbox:xmin() + dsrc, self.bbox:ymin() + dsrc, self.bbox:zmin())
	src :pt2(self.bbox:xmax() - dsrc, self.bbox:ymax() - dsrc, self.bbox:zmax() )
	src :signal(self.psig)
	src :direction(forward)
	src :point_size(2)

	src:enable_plane(yx)
	src:enable_plane(yz)
	src:enable_plane(zy)
	src:enable_plane(xz)
	src:enable_plane(zx)
	
	src:disable_plane(yx)
	src:disable_plane(xy)

	--src :is_point(false)
	 -- src :is_fill(false)
	--src :is_OutLine(true)
	src:rotate_uvw(yAxis,-pi/2)
	src:rotate_uvw(zAxis,pi/180*theta)
	src :outline_width(1.5)
	Geometry.AddSrc(src)
	-------------------------------------
end


function RCS2D:create_farbox(  )
	print( "create farbox")	
	local dfarbox = self.farbox_info.dfarbox 
	local strFreq="";
	for k,v in pairs (self.farbox_info.freq) do
		strFreq = strFreq..v..";"
	end
	---------------------------
	--FarField Box
	local farbox = Geometry.Near2FarFieldBox:new("fbox")
	farbox :pt1(self.bbox:xmin()+dfarbox,self.bbox:ymin()+dfarbox,self.bbox:zmin())
	farbox :pt2(self.bbox:xmax()-dfarbox, self.bbox:ymax()-dfarbox,self.bbox:zmax())
	farbox :angle_theta(90,360,1)
	farbox :angle_phi(0,360,361)
	 farbox :freq(strFreq)
	-- farbox :is_point(true)
	-- farbox :is_outline(true)
	 farbox :is_fill(false)
	farbox :signal(self.psig )	
	
	farbox:disable_plane(yx)
	farbox:disable_plane(xy)
	
	Geometry.AddProbe(farbox)
	----------------------------
end


function RCS2D:create_grabber(  )
	print( "create grabber")	
	 local cm = Geometry.CGLColorMap:new("Jet0")
	 local  probe = Geometry.TransientFieldsGrabber:new();
	 probe :name("Grabber-xy("..self.name..")");
	 probe :camera(self.camera)
	  probe :save2file(self.save2file);
	 probe :frame_delay(20);
	 probe :size(600,450);
	 probe :add_slice(cm,scalar_e,xy,0,2,false)
	 -- probe :add_slice(cm,ez,yz,0,2)
	  -- probe :is_fill(false);
	 -- probe:fields_types(ez,hx)
	 probe :stride(20);
	 Geometry.AddTransientFieldsGrabber(probe)
	----------------------------
end

-----------------------------------------------------------------------------
--后处理
function RCS2D:post_run ()
	print( "update probe fbox..." )
	Geometry.find_probe("fbox") :update()
	Geometry.find_probe("fbox") :save( self.name..".txt", "dBsm" )
	print( "save geometry..." )
	Geometry.SaveGeometry( self.name..".gap")
	print( "save summary..." )
	Geometry.save_summary( self.name.."-calculation-info.txt")
end
-----------------------------------------------------------------------------

return RCS2D;